﻿/*
 * TokyoTyrant.NET (http://tokyotyrant.codeplex.com)
 * Pure .NET interface to Tokyo Tyrant
 * Copyright (C) 2009 Russell van der Walt (http://blog.ruski.co.za)

 * TokyoTyrant.NET is free software; you can redistribute it and/or modify it under the terms of
 * the Microsoft Public License (Ms-PL). TokyoTyrant.NET is distributed in the hope
 * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the Microsoft Public
 * License for more details.
 * 
 * Tokyo Cabinet and Tokyo Tyrant is Copyright (C) 2006-2008 Mikio Hirabayashi 
 * http://tokyocabinet.sourceforge.net/
 * 
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace TokyoTyrant.NET {

    public enum TokyoQueryOperation {
        QCSTREQ = 0, // # query condition: string is equal to
        QCSTRINC = 1, // # query condition: string is included in
        QCSTRBW = 2, // # query condition: string begins with
        QCSTREW = 3, // # query condition: string ends with
        QCSTRAND = 4, // # query condition: string includes all tokens in
        QCSTROR = 5, // # query condition: string includes at least one token in
        QCSTROREQ = 6, // # query condition: string is equal to at least one token in
        QCSTRRX = 7, // # query condition: string matches regular expressions of
        QCNUMEQ = 8, // # query condition: number is equal to
        QCNUMGT = 9, // # query condition: number is greater than
        QCNUMGE = 10, // # query condition: number is greater than or equal to
        QCNUMLT = 11, // # query condition: number is less than
        QCNUMLE = 12, // # query condition: number is less than or equal to
        QCNUMBT = 13, // # query condition: number is between two tokens of
        QCNUMOREQ = 14, // # query condition: number is equal to at least one token in
        QCNEGATE = 1 << 24, // # query condition: negation flag
        QCNOIDX = 1 << 25 // # query condition: no index flag
    }

    public enum TokyoQueryOrder {
        QOSTRASC = 0, // # order type: string ascending
        QOSTRDESC = 1, // # order type: string descending
        QONUMASC = 2, // # order type: number ascending
        QONUMDESC = 3 // # order type: number descending
    }

    public class TokyoQuery {

        List<string> _args = new List<string>();

        IList<TokyoQueryItem> _items = new List<TokyoQueryItem>();

        public IList<TokyoQueryItem> Items {
            get { return _items; }
        }

        void AddCondition(TokyoQueryOperation operation, string column, string expr) {
            _args.Add("addcond" + "\0" + column + "\0" + ((int)operation).ToString() + "\0" + expr);
        }

        public TokyoQuery StringEquals(string column, string value) {
            AddCondition(TokyoQueryOperation.QCSTREQ, column, value);
            return this;
        }

        public TokyoQuery StringIn(string column, string value) {
            AddCondition(TokyoQueryOperation.QCSTRINC, column, value);
            return this;
        }

        public TokyoQuery StringStartsWith(string column, string value) {
            AddCondition(TokyoQueryOperation.QCSTRBW, column, value);
            return this;
        }

        public TokyoQuery StringEndsWith(string column, string value) {
            AddCondition(TokyoQueryOperation.QCSTREW, column, value);
            return this;
        }

        public TokyoQuery NumberEquals(string column, int value) {
            AddCondition(TokyoQueryOperation.QCNUMEQ, column, value.ToString());
            return this;
        }

        public TokyoQuery NumberGreaterThan(string column, int value) {
            AddCondition(TokyoQueryOperation.QCNUMGT, column, value.ToString());
            return this;
        }

        public TokyoQuery NumberGreaterThanOrEqual(string column, int value) {
            AddCondition(TokyoQueryOperation.QCNUMGE, column, value.ToString());
            return this;
        }

        public TokyoQuery NumberLessThan(string column, int value) {
            AddCondition(TokyoQueryOperation.QCNUMLT, column, value.ToString());
            return this;
        }

        public TokyoQuery NumberLessThanOrEqual(string column, int value) {
            AddCondition(TokyoQueryOperation.QCNUMLE, column, value.ToString());
            return this;
        }

        public TokyoQuery OrderBy(string column, TokyoQueryOrder order) {
            _args.Add("setorder" + "\0" + column + "\0" + ((int)order).ToString());
            return this;
        }

        public TokyoQuery LimitTo(int max, int skip) {
            _args.Add("setlimit" + "\0" + max.ToString() + "\0" + skip.ToString());
            return this;
        }

        public string[] GetArgs() {
            return _args.ToArray();           
        }


    }

    public class TokyoQueryItem {

        public TokyoQueryItem(TokyoQueryOperation operation, string column, string expression) {
            this.Operation = operation;
            this.Column = column;
            this.Expression = expression;
        }


        public TokyoQueryOperation Operation { get; set; }
        public string Column { get; set; }
        public string Expression { get; set; }

    }

}
